package com.mhy.dingrobot

import android.util.Base64
import com.dingtalk.api.DefaultDingTalkClient
import com.dingtalk.api.DingTalkClient
import com.dingtalk.api.request.OapiRobotSendRequest
import com.dingtalk.api.request.OapiRobotSendRequest.At
import com.dingtalk.api.response.OapiRobotSendResponse
import org.json.JSONObject
import java.io.ByteArrayOutputStream
import java.net.HttpURLConnection
import java.net.URL
import java.net.URLEncoder
import javax.crypto.Mac
import javax.crypto.spec.SecretKeySpec


/**
 * Created By Mahongyin
 * Date    2021/1/3 3:01
 */
class Robot {
   private lateinit var client: DingTalkClient
   private lateinit var  request :OapiRobotSendRequest
   private var basrUrl=""
    constructor(token: String) {
         basrUrl = "https://oapi.dingtalk.com/robot/send?access_token=$token"
         client= DefaultDingTalkClient(basrUrl)
         request = OapiRobotSendRequest()
    }

    constructor(token: String, secret: String) {
        val single=setSign(secret)
         basrUrl ="https://oapi.dingtalk.com/robot/send?access_token=$token${single}"
        client = DefaultDingTalkClient(basrUrl)
         request = OapiRobotSendRequest()
    }

    @Throws(Exception::class)
    fun sendTextMsg(content: String, atMobiles: List<String>, atAll: Boolean = false): OapiRobotSendResponse? {
        request.msgtype = "text"
        val text = OapiRobotSendRequest.Text()
        text.content = content
        request.setText(text)
        val at = At()
        at.atMobiles = atMobiles  as ArrayList<String>//Arrays.asList("132xxxxxxxx")
        // isAtAll类型如果不为Boolean，请升级至最新SDK
        at.isAtAll = atAll
        request.setAt(at)
        val response = client.execute(request)
        return response
    }

    @Throws(Exception::class)
    fun sendLinkMsg(linkUrl: String, picUrl: String = "", title: String, content: String): OapiRobotSendResponse? {
        request.msgtype = "link"
        val link = OapiRobotSendRequest.Link()
        link.messageUrl = linkUrl
        link.picUrl = picUrl
        link.title = title
        link.text = content
        request.setLink(link)
        val response = client.execute(request)
        return response
    }

    @Throws(Exception::class)
    fun sendMarkDownMsg(
        title: String,
        content: String,
        atMobiles: List<String>,
        atAll: Boolean = false
    ): OapiRobotSendResponse? {
        request.msgtype = "markdown"
        val markdown = OapiRobotSendRequest.Markdown()
        markdown.title = title
        markdown.text = content
//        """
//            #### 杭州天气 @156xxxx8827
//            > 9度，西北风1级，空气良89，相对温度73%
//
//            > ![screenshot](https://gw.alicdn.com/tfs/TB1ut3xxbsrBKNjSZFpXXcXhFXa-846-786.png)
//            > ###### 10点20分发布 [天气](http://www.thinkpage.cn/)
//
//            """.trimIndent()
        request.setMarkdown(markdown)
        val at = At()
        at.atMobiles = atMobiles as ArrayList<String>//Arrays.asList("132xxxxxxxx")
        // isAtAll类型如果不为Boolean，请升级至最新SDK
        at.isAtAll = atAll
        request.setAt(at)
        val response = client.execute(request)
        return response
    }

    /**
     * {
    "actionCard": {
    "title": "乔布斯 20 年前想打造一间苹果咖啡厅，而它正是 Apple Store 的前身",
    "text": "![screenshot](https://gw.alicdn.com/tfs/TB1ut3xxbsrBKNjSZFpXXcXhFXa-846-786.png)
    ### 乔布斯 20 年前想打造的苹果咖啡厅
    Apple Store 的设计正从原来满满的科技感走向生活化，而其生活化的走向其实可以追溯到 20 年前苹果一个建立咖啡馆的计划",
    "btnOrientation": "0",
    "singleTitle" : "阅读全文",
    "singleURL" : "https://www.dingtalk.com/"
    },
    "msgtype": "actionCard"
    }
     */
    @Throws(Exception::class)
    fun sendActionCardMsg(title: String, content: String, urlTitle: String, linkUrl: String): OapiRobotSendResponse? {
        //actionCard feedCard
        request.msgtype = "actionCard"
        val actioncard = OapiRobotSendRequest.Actioncard()
        actioncard.singleURL = linkUrl
        actioncard.singleTitle = urlTitle
        actioncard.title = title
        actioncard.text = content
        request.setActionCard(actioncard)
        val response = client.execute(request)
        return response
    }

    /**
     * {
    "actionCard": {
    "title": "乔布斯 20 年前想打造一间苹果咖啡厅，而它正是 Apple Store 的前身",
    "text": "![screenshot](https://gw.alicdn.com/tfs/TB1ut3xxbsrBKNjSZFpXXcXhFXa-846-786.png)
    ### 乔布斯 20 年前想打造的苹果咖啡厅
    Apple Store 的设计正从原来满满的科技感走向生活化，而其生活化的走向其实可以追溯到 20 年前苹果一个建立咖啡馆的计划",
    "btnOrientation": "0",//0-按钮竖直排列，1-按钮横向排列
    "btns": [
    {
    "title": "内容不错",
    "actionURL": "https://www.dingtalk.com/"
    },
    {
    "title": "不感兴趣",
    "actionURL": "https://www.dingtalk.com/"
    }
    ]
    },
    "msgtype": "actionCard"
    }
     */

    @Throws(Exception::class)
    fun sendActionCardListMsg(
        title: String,
        content: String,
        btnOrientation: String = "0",
        title_linkurl: List<OapiRobotSendRequest.Btns>
    ): OapiRobotSendResponse? {
        request.msgtype = "actionCard"
        val actioncard = OapiRobotSendRequest.Actioncard()
        actioncard.title = title
        actioncard.text = content
        actioncard.btnOrientation=btnOrientation
        actioncard.btns=title_linkurl
        request.setActionCard(actioncard)
        val response = client.execute(request)
        return response
    }

    /**
     * {
    "feedCard": {
    "links": [
    {
    "title": "时代的火车向前开",
    "messageURL": "https://www.dingtalk.com/s?__biz=MzA4NjMwMTA2Ng==&mid=2650316842&idx=1&sn=60da3ea2b29f1dcc43a7c8e4a7c97a16&scene=2&srcid=09189AnRJEdIiWVaKltFzNTw&from=timeline&isappinstalled=0&key=&ascene=2&uin=&devicetype=android-23&version=26031933&nettype=WIFI",
    "picURL": "https://gw.alicdn.com/tfs/TB1ayl9mpYqK1RjSZLeXXbXppXa-170-62.png"
    },
    {
    "title": "时代的火车向前开2",
    "messageURL": "https://www.dingtalk.com/s?__biz=MzA4NjMwMTA2Ng==&mid=2650316842&idx=1&sn=60da3ea2b29f1dcc43a7c8e4a7c97a16&scene=2&srcid=09189AnRJEdIiWVaKltFzNTw&from=timeline&isappinstalled=0&key=&ascene=2&uin=&devicetype=android-23&version=26031933&nettype=WIFI",
    "picURL": "https://gw.alicdn.com/tfs/TB1ayl9mpYqK1RjSZLeXXbXppXa-170-62.png"
    }
    ]
    },
    "msgtype": "feedCard"
    }
     */
    @Throws(Exception::class)
    fun sendFeedCardListMsg(link: List<OapiRobotSendRequest.Links>): OapiRobotSendResponse? {
        //actionCard feedCard
        request.msgtype = "feedCard"
        val feedcard = OapiRobotSendRequest.Feedcard()
        feedcard.links = link
        request.setFeedCard(feedcard)
        val response = client.execute(request)
        return response
    }
    /**
     * 安全设置目前有3种方式：
    （1）方式一，自定义关键词
    最多可以设置10个关键词，消息中至少包含其中1个关键词才可以发送成功。
    例如：添加了一个自定义关键词：监控报警
    则这个机器人所发送的消息，必须包含 监控报警 这个词，才能发送成功。
    （2）方式二，加签
    第一步，把timestamp+"\n"+密钥当做签名字符串，使用HmacSHA256算法计算签名，然后进行Base64 encode，最后再把签名参数再进行urlEncode，得到最终的签名（需要使用UTF-8字符集）。
    参数说明
    timestamp当前时间戳，单位是毫秒，与请求调用时间误差不能超过1小时
    secret密钥，机器人安全设置页面，加签一栏下面显示的SEC开头的字符串
    第二步，把 timestamp和第一步得到的签名值拼接到URL中。
    参数说明
    timestamp第一步使用到的时间戳
    sign第一步得到的签名值
    https://oapi.dingtalk.com/robot/send?access_token=XXXXXX&timestamp=XXX&sign=XXX
    （3）方式三，IP地址（段）
    设定后，只有来自IP地址范围内的请求才会被正常处理。支持两种设置方式：IP、IP段，暂不支持IPv6地址白名单，格式如下:
    image.png
    注意：安全设置的上述三种方式，需要至少设置其中一种，以进行安全保护。校验不通过的消息将会发送失败，错误如下：
    // 签名不匹配
    {
    "errcode":310000,
    "errmsg":"sign not match"
    }
     */

    @Throws(Exception::class)
    private fun setSign(secret: String): String {
        val timestamp = System.currentTimeMillis()
        val stringToSign = """
                $timestamp
                $secret
                """.trimIndent()
        val mac = Mac.getInstance("HmacSHA256")
        mac.init(SecretKeySpec(secret.toByteArray(charset("UTF-8")), "HmacSHA256"))
        val signData = mac.doFinal(stringToSign.toByteArray(charset("UTF-8")))
        val sign = URLEncoder.encode(String(Base64.encode(signData, Base64.DEFAULT)), "UTF-8")
        return "&timestamp=$timestamp&sign=$sign"
    }

    suspend  fun sendJson(json: String): OapiRobotSendResponse? {
        var msg: String? = ""
        val oapiRobotSendRequest=OapiRobotSendResponse()
        try {
            val conn = URL(basrUrl).openConnection() as HttpURLConnection
            //设置请求方式,请求超时信息
            conn.requestMethod = "POST"
            conn.readTimeout = 5000
            conn.connectTimeout = 5000
            //设置运行输入,输出:
            conn.doOutput = true
            conn.doInput = true
            //Post方式不能缓存,需手动设置为false
            conn.useCaches = false
            //我们请求的数据:
            //这里可以写一些请求头的东东...

            //获取输出流
            val out = conn.outputStream
            out.write(json.toByteArray())
            out.flush()
            if (conn.responseCode == 200) {
                // 获取响应的输入流对象
                val inputStream = conn.inputStream
                // 创建字节输出流对象
                val message = ByteArrayOutputStream()
                // 定义读取的长度
                var len = 0
                // 定义缓冲区
                val buffer = ByteArray(1024)
                // 按照缓冲区的大小，循环读取
                while (inputStream.read(buffer).also { len = it } != -1) {
                    // 根据读取的长度写入到os对象中
                    message.write(buffer, 0, len)
                }
                // 释放资源
                inputStream.close()
                message.close()
                // 返回字符串
                msg = String(message.toByteArray())
                val obj = JSONObject(msg)
                val errcode: Int = obj.getInt("errcode")
                oapiRobotSendRequest.setErrorCode("$errcode")
                oapiRobotSendRequest.setErrmsg(obj.getString("errmsg"))
                return oapiRobotSendRequest
            }
        } catch (e: Exception) {
            e.printStackTrace()
        }
        return oapiRobotSendRequest
    }
}